#include "livetrack.h"

#include "gps_leg.h"
#include "statstracks.h"

#include "controls/ftmessagebox.h"
#include "controls/filebrowser.h"
#include "controls/ftlabel.h"
#include "controls/ftpushbutton.h"
#include "controls/ftlist.h"
#include "controls/ftpushbuttonicon.h"
#include "controls/fttabwidget.h"
#include "controls/ftcheckbox.h"
#include "controls/ftlatlonedit.h"
#include "controls/ftlineedit.h"
#include "controls/ftvboxlayout.h"
#include "controls/fthboxlayout.h"
#include "controls/fttextarea.h"

#include "workers/workerloadgpx.h"
#include "workers/workersavegpx.h"

#define MINIMUM_DISTANCE 5

LiveTrack::LiveTrack() :
    RotatingWidget()
{
    // Initialize active leg
    _activeLeg = -1;

    _track = new GPS_track();
    _track->setTitle( tr("Untitled LiveTrack") );
    _track->setDescription( tr("No Description") );
    _track->unModify();

    minimumDop = configuration->minimumDop();
    connect( configuration, SIGNAL(minimumDopChanged(int)),
             this, SLOT(updateMinimumDOP(int)));

    // Create all the dialog widgets...
    livetrackTab = new FTTabWidget( FTTabWidget::with_header );
    connect( livetrackTab, SIGNAL(currentChanged()),
             this, SLOT(pageChanged() ) );
    buildDialogMain();
    buildDialogLegs();
    buildDialogWaypoints();
    builddialogStats();
    // Initialize filename to empty
    updateFilename("");

    // Load defaults from configuration...
    track_mode = configuration->trackingMode( track_value );

    if ( autosaver.initialize( this ) )
    {
        // Initialize content of the widgets
        updateInfoLabel();
        populateListLegs();
        populateListWaypoints();
        titleEdit->setText( _track->title() );
        descEdit->setText( _track->description() );
    }
}

LiveTrack::~LiveTrack()
{
    delete _track;
}

void LiveTrack::updateMinimumDOP(int d)
{
    minimumDop = d;
}

void LiveTrack::prepareToQuit()
{
    // Definitely disable tracking, we dont need it anymore for this session!
    _trackingActive = false;
    if ( _track->modified() )
    {
        bool do_save = true;
        // When filename is not set, always ask if user wants to save.
        // When filename is set, ask to save ONLY if autosave is not set, otherwise always save.
        if ( !autosaver.AutosaveEnabled() || ( _filename == "" ) )
            do_save = FTMessageBox::Yesno(tr("Save LiveTrack"),
                                          tr("Save current LiveTrack before quit?") );
        if ( do_save )
        {
            saveTrack();
            autosaver.AutosaveStop();
        }
    }
}

const GPS_point* LiveTrack::lastPoint() const
{
    const GPS_leg* my_leg;
    if ( ( my_leg = _track->leg( _activeLeg)) != NULL )
    {
        return my_leg->lastPoint();
    }
    return NULL;
}

void LiveTrack::updateFilename(const QString& f )
{
    _filename = f;
    QFileInfo qfi( _filename );
    filenameLabel->setText( tr("File:") + " " +
                            (f == "" ? tr("-- not set--") : qfi.fileName()) );
}

void LiveTrack::setFilename(const QString & f)
{
    updateFilename(f);
    autosaver.AutosaveFilename( _filename );
}

bool LiveTrack::trackingActive() const
{
    return _trackingActive;
}

GPS_track* LiveTrack::track() const
{
    return _track;
}

void LiveTrack::trackingModeChanged(Configuration::tracking_mode tm, int tv)
{
    track_mode = tm;
    track_value = tv;
}

void LiveTrack::toggleTracking()
{
    startTracking( !_trackingActive );
}

void LiveTrack::startTracking(bool s)
{
    // Dont do anything if our state matches the requested state
    if ( s == _trackingActive )
        return;

    // Start tracking...
    if ( s )
    {
        if ( (_filename == "") &&
             (configuration->livetrackAutosave()) &&
             FTMessageBox::Yesno( tr("Start LiveTrack..."),
                                      tr("Save LiveTrack?") ) )
        {
            QStringList filters;
            filters << "*gpx";
            QString savefile = FileBrowser::browseFilename(FileBrowser::saveMode,
                                                           tr("Save LiveTrack"),
                                                           configuration->defaultPath(),
                                                           filters);
            if ( ( savefile != "") && !savefile.endsWith(".gpx") )
                savefile += ".gpx";
            setFilename( savefile );
        }

        if ( _activeLeg == -1 )
        {
            if ( _track->listLegs().count() > 0 )
            {
                if ( !FTMessageBox::Yesno( tr("Create new leg?"),
                                          tr("If you proceed, a new leg will be created. If you want "\
                                             "to use an existing leg, please activate it first."),
                                          tr("Create new leg"),
                                          tr("Cancel") ) )
                    return;
            }
            GPS_leg* new_leg = new GPS_leg();
            _track->addLeg( new_leg );
            _activeLeg = new_leg->id();
            populateListLegs();
            autosaver.AutosaveLeg(new_leg);
            autosaver.AutosaveActiveLeg(_activeLeg);
            updateInfoLabel();
        }

        _trackingActive = true;
        startButton->setText( tr("Stop tracking...") );
        startButton->setIcon( QIcon( ":/livetrack/stop_tracking.png") );

    }
    else // Stop tracking...
    {
        _trackingActive = false;
        startButton->setText( tr("Start tracking...") );
        startButton->setIcon( QIcon( ":/livetrack/start_tracking.png") );
    }
    startButton->setChecked( _trackingActive );
    emit trackingStatusChanged( _trackingActive );
}

void LiveTrack::loadTrack()
{
    // Modified track? Ask if user wants to save...
    if ( _track->modified() )
    {
        int answer = FTMessageBox::Question( tr("Load LiveTrack"),
                                                        tr("Discard current track, save current track or abort loading"),
                                                        tr("Discard"),
                                                        tr("Save"),
                                                        tr("Abort") );
        if ( answer == 2 )
            return; // Abort clear!
        else if ( answer == 1 )
            saveTrack(); // Save before clearing!
    }

    // Inhibit tracking to avoid the "random points in the middle of a track" bug
    trackingLock(true);

    // Get the new filename to load...
    QStringList filters;
    filters << "*gpx";
    QString new_filename = FileBrowser::browseFilename(FileBrowser::loadMode,
                                                       tr("Load live track..."),
                                                       configuration->defaultPath(),
                                                       filters);

    // Only if the user selected a valid file...
    if ( new_filename != "" )
    {
        // Stop any autosaving right now! (also removes file)
        autosaver.AutosaveStop();
        delete _track;
        _track = new GPS_track();
        _track->setTitle( tr("Untitled LiveTrack") );
        _track->setDescription( tr("No Description") );
        _track->unModify();

        updateFilename(new_filename);

        // Create the loader and run it
        WorkerLoadGpx worker( _filename, _track, tr("Loading GPX...") );
        if ( worker.run() )
            _track->unModify(); // Run ok... track is not modified.
        else
            FTMessageBox::Error( tr("Load error"), tr("Unable to load LiveTrack!") );

        // Update widgets...
        updateInfoLabel();
        populateListLegs();
        populateListWaypoints();

        // Precache autosave...
        autosaver.AutosavePrecache();
    }
    trackingLock(false);
}

void LiveTrack::saveTrack()
{
    trackingLock(true);
    if ( _filename == "")
        saveTrackAs();
    else
    {
        if ( _track->title() == "" )
            _track->setTitle( QFileInfo(_filename).fileName() );
        if ( _track->description() == "" )
            _track->setDescription( QDateTime::currentDateTime().toString("dd/MM/yyyy") );
        WorkerSaveGpx worker( _filename, _track, tr("Saving LiveTrack..."));
        if ( worker.run() )
            _track->unModify();
        else
            FTMessageBox::Error( tr("Save error"), tr("LiveTrack not saved!") );
    }
    trackingLock(false);
}

void LiveTrack::saveTrackAs()
{
    trackingLock(true);
    QStringList filters;
    filters << "*gpx";
    QString savefile = FileBrowser::browseFilename(FileBrowser::saveMode,
                                                   tr("Save LiveTrack..."),
                                                   configuration->defaultPath(),
                                                   filters);
    if ( ( savefile != "") && !savefile.endsWith(".gpx") )
        savefile += ".gpx";

    setFilename( savefile );
    if ( _filename != "" )
        saveTrack();
    trackingLock(false);
}

void LiveTrack::resetTrack()
{
    if ( _track->modified() &&
         !FTMessageBox::Yesno( tr("Reset LiveTrack"),
                              tr("Really reset?") ) )
        return;

    trackingLock(true);

    // Stop any autosaving right now! (also removes file)
    autosaver.AutosaveStop();

    _track->clearTrack();
    _track->setTitle( tr("") );
    _track->setDescription( tr("") );
    _track->unModify();
    _activeLeg = -1;

    titleEdit->setText( _track->title() );
    descEdit->setText( _track->description() );
    filenameLabel->setText( "" );
    populateListLegs();
    populateListWaypoints();
    updateInfoLabel();
    closeWaypointEdit();
    closeLegEdit();
    trackingLock(false);
}

void LiveTrack::trackingLock(bool lock)
{
    static int already_locked = 0;
    static bool stored_tracking = false;

    // On first lock request, lock...
    if ( lock && (already_locked == 0) )
    {
        already_locked = 1;
        stored_tracking = _trackingActive;
        _trackingActive = false;
    }
    // On subsequent lock requests, increment counter
    else if ( lock && (already_locked > 0 ) )
        already_locked++;
    // On last unlock request, unlock...
    else if ( !lock && (already_locked == 0 ) )
    {
        _trackingActive = stored_tracking;
    }
    else if ( !lock && (already_locked > 0 ) )
        already_locked--;
}



bool LiveTrack::checkAutomatic(const GPS_point& position, const GPS_point* myLast)
{
    // we do not append points overlapping the last one (assume spurious gps)
    // except in the case of a more precise point, wihch will override the last less precise point.
    if ( myLast->isOverlapping( position ) )
    {   // We check PDOP here... (lower is better)
        if ( myLast->dop().pdop() <= position.dop().pdop() )
            return false; // So we ignore the new point!
        // This point is more precise, so we remove the last point...
        _track->dropLastPointFromLeg( _activeLeg );
        autosaver.AutosaveBacktrack( _activeLeg );
    }
    return true;
}

bool LiveTrack::checkTimeMode(const GPS_point& position, const GPS_point* myLast)
{
    // If the difference is less than set threeshold...
    if ( (position.timestamp().toTime_t() - myLast->timestamp().toTime_t()) < (unsigned int)track_value )
        // dont store the point!
        return false;
    return true;
}

bool LiveTrack::checkDistanceMode(const GPS_point&, qreal distance)
{
    // if the last point is closer than the set threeshold...
    if ( distance < track_value )
        // dont store the point!
        return false;
    return true;
}

void LiveTrack::addPointFromGps(GPS_point position )
{
    // Ignore this point if we are not tracking
    if ( !_trackingActive )
        return;

    // Ignore any PDOP > 10 since points will be too imprecise to be usefull...
    if ( position.dop().pdop() > minimumDop )
        return;

    // Ignore points with more than 150mt of precision... They clearly come from some
    // non-gps or network-based method, but they are quite useless for a real track.
    if ( position.h_precision() > 150 )
        return;

    // NOTE: we will discard any point less than MINIMUM_DISTANCE...

    // We do not append points which have speed > 300 m/sec (about 1080km/h)
    // i doubt this will ever be used on military jets...
    if ( position.speed() >= 300.0 )
        return;

    const GPS_leg* current_leg;
    const GPS_point* myLast;
    if ( ( current_leg = _track->leg( _activeLeg ) ) == NULL )
        return; // no active leg???

    // If there is at least one point already stored, we need to check the tracking modes...
    if ( ( myLast = current_leg->lastPoint() ) != NULL )
    {
        int distance =  position.distanceTo( *myLast );
        // if the last point is closer than the set MINIMUM_DISTANCE...
        if ( distance < MINIMUM_DISTANCE )
            // dont store the point!
            return;

        // Automatic trackmode might remove the last point...
        if ( track_mode == Configuration::automatic_trackmode )
        {
            if ( !checkAutomatic(position, myLast) )
                return;
        }

        // time based trackmode might skip this point if not enough time has passed...
        else if ( track_mode == Configuration::time_trackmode )
        {
            if ( !checkTimeMode(position, myLast) )
                return;
        }

         // Distance based trackmode might skip this point if too close
        else if ( track_mode == Configuration::distance_trackmode )
        {
            if ( !checkDistanceMode(position, distance) )
                return;
        }

         else // invalid track mode, ignore point
             return;
    }

    // Now append the new valid point! (NOTE: we save a COPY in the heap!
    GPS_point* new_position = new GPS_point(position);
    if ( !_track->addPointToLeg( new_position, _activeLeg ) )
        delete new_position;
    else
    {
        updateInfoLabel();
        // Check if we must autosave the track
        autosaver.AutosavePoint( _activeLeg, &position );

        // inform the world we have a new point!!!
        emit trackChanged( current_leg->nPoints(), current_leg->lengthMt() );
    }
}

void LiveTrack::buildDialogMain()
{
    mainPage = new QWidget();
    livetrackTab->addTab( mainPage, tr("Live!") );

    titleLabel = new FTLabel( tr("LiveTrack title:") );
    titleEdit = new FTLineEdit( _track->title() );
    connect( titleEdit, SIGNAL(textEdited(QString)),
             this, SLOT(titleUpdated(QString)));

    descLabel = new FTLabel( tr("Description:") );
    descEdit = new QLineEdit( _track->description() );
    connect( descEdit, SIGNAL(textEdited(QString)),
             this, SLOT(descUpdated(QString)));

    filenameLabel = new FTLabel("");

    filenamesaveButton = new FTPushButtonIcon( QIcon(":/misc/save.png"), FTControls::IconBig );
    connect( filenamesaveButton, SIGNAL(clicked()),
             this, SLOT(saveTrackAs()));

    filenameloadButton = new FTPushButtonIcon( QIcon(":/misc/load.png"), FTControls::IconBig );
    connect( filenameloadButton, SIGNAL(clicked()),
             this, SLOT(loadTrack()));

    resetButton = new FTPushButtonIcon( QIcon(":/livetrack/reset.png"), FTControls::IconBig );
    connect( resetButton, SIGNAL(clicked()),
             this, SLOT(resetTrack()));

    startButton = new FTPushButton( tr("Start tracking...") );
    startButton->setIcon( QIcon(":/livetrack/start_tracking.png") );
    startButton->setCheckable(true);
    connect( startButton, SIGNAL(clicked(bool)),
             this, SLOT(startTracking(bool)) );

    infoLabel = new FTTextArea( ".. / .. / .. ");
    infoLabel->setAlignment( Qt::AlignCenter );
}

void LiveTrack::buildDialogLegs()
{
    legsPage = new QWidget();
    livetrackTab->addTab( legsPage, tr("Legs") );

    newlegButton = new FTPushButton( tr("New leg" ) );
    newlegButton->setIcon( QIcon( ":/misc/new.png" ) );
    connect( newlegButton, SIGNAL(clicked()),
             this, SLOT( createNewLeg()) );

    legsList = new FTList();
    connect( legsList, SIGNAL(keySelected(int)),
             this, SLOT(editLeg(int)));

    editlegPane = new QWidget();
    editlegPane->setVisible(false);

    legnameLabel = new FTLabel( tr("Leg name:" ) );
    legnameEdit = new QLineEdit();

    legcolorButton = new FTPushButton( tr("leg color") );
    connect( legcolorButton, SIGNAL(clicked()),
             this, SLOT(setColorLeg()));

    savelegButton = new FTPushButton( tr("Save leg" ) );
    connect( savelegButton, SIGNAL(clicked()),
             this, SLOT(confirmLeg()) );

    ignorelegButton = new FTPushButton( tr("cancel") );
    connect( ignorelegButton, SIGNAL(clicked()),
             this, SLOT(ignoreLeg()));

    activelegButton = new FTCheckBox( tr("Set active") );
    connect( activelegButton, SIGNAL(clicked()),
             this, SLOT(changeActiveLeg()) );

    deletelegButton = new FTPushButtonIcon( QIcon( ":/misc/delete.png" ),
                                            FTControls::IconNormal );
    connect( deletelegButton, SIGNAL(clicked()),
             this, SLOT( removeLeg()) );

}

void LiveTrack::builddialogStats()
{
    stats = new StatsTracks();
    livetrackTab->addTab( stats, QIcon(":/livetrack/stats.png"));
}

void LiveTrack::buildDialogWaypoints()
{
    waypointsPage = new QWidget();
    livetrackTab->addTab( waypointsPage, QIcon(":/table/waypoint.png") );

    waypointsList = new FTList();
    connect( waypointsList, SIGNAL(keySelected(int)),
             this, SLOT(editWaypoint(int)));

    editwaypointPane = new QWidget();
    editwaypointPane->setVisible(false);

    waypointnameLabel = new FTLabel( tr("Waypoint name:" ) );
    waypointnameEdit = new QLineEdit();

    waypointdescLabel = new FTLabel( tr("Description:" ) );
    waypointdescEdit = new QLineEdit();

    waypointlatlonEdit = new FTLatLonEdit();

    waypointeleLabel = new FTLabel( tr("Elevation (mt):" ) );
    waypointeleEdit = new QLineEdit();

    waypointcolorButton = new FTPushButton( tr("Color") );
    connect( waypointcolorButton, SIGNAL(clicked()),
             this, SLOT(setColorWaypoint()));

    savewaypointButton = new FTPushButton( tr("Save Waypoint" ) );
    connect( savewaypointButton, SIGNAL(clicked()),
             this, SLOT(confirmWaypoint()) );

    ignorewaypointButton = new FTPushButton( tr("cancel") );
    connect( ignorewaypointButton, SIGNAL(clicked()),
             this, SLOT(ignoreWaypoint()));

    deletewaypointButton = new FTPushButtonIcon( QIcon( ":/misc/delete.png" ),
                                                 FTControls::IconNormal );
    connect( deletewaypointButton, SIGNAL(clicked()),
             this, SLOT( removeWaypoint()) );

    gotoButton = new FTPushButton( tr("Go to...") );
    connect( gotoButton, SIGNAL(clicked()),
             this, SLOT( gotoWaypoint()));

}

void LiveTrack::createWaypoint(double lat, double lon, int alt)
{
    createNewWaypoint();
    waypointlatlonEdit->setLatLon(lat,lon);
    waypointeleEdit->setText( QString("%1").arg(alt) );
    livetrackTab->setCurrentWidget(  waypointsPage );
    emit livetrackPopup();
}

void LiveTrack::createNewWaypoint()
{
    isNewWaypoint = true;
    selectedWaypointId = -1;
    openWaypointEdit();
}

void LiveTrack::editWaypoint(int id)
{
    if ( _track->waypoint(id) != NULL )
    {
        isNewWaypoint = false;
        selectedWaypointId = id;
        openWaypointEdit();
    }
    else
    {
        selectedWaypointId = -1;
        closeWaypointEdit();
    }
}

void LiveTrack::openWaypointEdit()
{
    if ( isNewWaypoint )
    {
        tmpWaypointColor = QColor("red");
        waypointnameEdit->setText( tr("New Waypoint") );
        waypointdescEdit->setText( "" );
        waypointeleEdit->setText( 0 );
        waypointlatlonEdit->setLatLon( 0.0, 0.0 );
        waypointcolorButton->setCustomBackground( tmpWaypointColor );
        waypointsList->setVisible( false );
        editwaypointPane->setVisible(true);
    }
    else
    {
        const GPS_waypoint* myWp = _track->waypoint( selectedWaypointId );
        if (  myWp != NULL )
        {
            tmpWaypointColor = myWp->color();
            waypointnameEdit->setText( myWp->name() );
            waypointdescEdit->setText( myWp->description() );
            waypointeleEdit->setText( QString("%1").arg(myWp->altitude()) );
            waypointlatlonEdit->setLatLon( myWp->latitude(), myWp->longitude() );
            waypointcolorButton->setCustomBackground( tmpWaypointColor );
            waypointsList->setVisible( false );
            editwaypointPane->setVisible(true);
        }
    }
}

void LiveTrack::closeWaypointEdit()
{
    waypointsList->setVisible( true );
    editwaypointPane->setVisible(false);
}

void LiveTrack::removeWaypoint()
{
    if ( selectedWaypointId != -1 )
    {
        if ( FTMessageBox::Yesno( tr("Delete waypoint"),
                                  tr("Really delete waypoint?") ) )
        {
            _track->deleteWaypoint( selectedWaypointId );
            autosaver.AutosaveDeleteWaypoint( selectedWaypointId );
            closeWaypointEdit();
            populateListWaypoints();
        }
    }
}

void LiveTrack::confirmWaypoint()
{
    // Close edit widget first...
    closeWaypointEdit();

    GPS_waypoint* myWp;
    if ( isNewWaypoint )
    {   // Add new leg and get its ID
        myWp = new GPS_waypoint();
        selectedWaypointId = myWp->id();
    }
    else
    {   // Get leg from track
        myWp = _track->waypointMod( selectedWaypointId );
    }

    if ( myWp != NULL )
    {
        // Save color&title
        myWp->setName( waypointnameEdit->text() );
        myWp->setDescription( waypointdescEdit->text() );
        myWp->setLatitude( waypointlatlonEdit->latitude() );
        myWp->setLongitude( waypointlatlonEdit->longitude() );
        myWp->setAltitude( waypointeleEdit->text().toInt() );
        myWp->setColor( tmpWaypointColor );
        // Update leg to track
        _track->waypointUpdated( myWp );

        updateInfoLabel();
        populateListWaypoints();
    }
}

void LiveTrack::ignoreWaypoint()
{
    selectedWaypointId = -1;
    isNewWaypoint = false;
    closeWaypointEdit();
}

void LiveTrack::gotoWaypoint()
{
    const GPS_waypoint* wp = _track->waypoint( selectedWaypointId );
    if ( wp != NULL )
    {
        emit setDestination( *wp );
        FTMessageBox::Info( tr("Destination set"), tr("Waypoint set as destination!") );
    }
}

void LiveTrack::setColorWaypoint()
{
    tmpWaypointColor = FTMessageBox::Color( tr("Waypoint color"), tr("Select color"), tmpWaypointColor );
    waypointcolorButton->setCustomBackground( QBrush( tmpWaypointColor ) );
}

void LiveTrack::populateListLegs()
{
    QList<int> legs_id = _track->listLegs();
    legsList->clear();
    foreach (int leg_id, legs_id )
    {
        const GPS_leg* leg = _track->leg( leg_id );
        if (  leg != NULL )
        {
            legsList->appendString( ((leg_id == _activeLeg) ? "(a) " : "") + leg->title(), leg_id );
        }
    }
    selectedLegId = -1;
}

void LiveTrack::populateListWaypoints()
{
    QList<int> wp_ids = _track->listWaypoints();
    waypointsList->clear();
    foreach (int wp_id, wp_ids )
    {
        const GPS_waypoint* wp = _track->waypoint( wp_id );
        if ( wp != NULL )
        {
            waypointsList->appendString( QString("%1: %2,%3").arg(wp->name())
                                                       .arg(wp->LatToString())
                                                       .arg(wp->LonToString()),
                                         wp_id);
        }
    }
}

void LiveTrack::titleUpdated(QString t)
{
    _track->setTitle(t);
    autosaver.AutosaveTitle(t);
}

void LiveTrack::descUpdated(QString d)
{
    _track->setDescription(d);
    autosaver.AutosaveDescription(d);
}

void LiveTrack::createNewLeg()
{
    isNewLeg = true;
    selectedLegId = -1;
    openLegEdit();
}

void LiveTrack::editLeg(int id)
{
    if ( _track->leg( id ) != NULL )
    {
        isNewLeg = false;
        selectedLegId = id;
        openLegEdit();
    }
    else
    {
        selectedLegId = -1;
        closeLegEdit();
    }
}

void LiveTrack::openLegEdit()
{
    if ( isNewLeg )
    {
        tmpLegColor = QColor("red");
        legnameEdit->setText( tr("New Leg") );
        legcolorButton->setCustomBackground( tmpLegColor );
        legsList->setVisible( false );
        newlegButton->setVisible( false );
        editlegPane->setVisible(true);
        activelegButton->setChecked( _activeLeg == -1 );
    }
    else
    {
        const GPS_leg* myLeg = _track->leg( selectedLegId );
        if ( myLeg != NULL )
        {
            tmpLegColor = myLeg->color();
            legnameEdit->setText( myLeg->title() );
            legcolorButton->setCustomBackground( tmpLegColor );
            legsList->setVisible( false );
            newlegButton->setVisible( false );
            editlegPane->setVisible(true);
            activelegButton->setChecked( _activeLeg == selectedLegId );
        }
    }
}

void LiveTrack::closeLegEdit()
{
    newlegButton->setVisible( true );
    legsList->setVisible( true );
    editlegPane->setVisible(false);
}

void LiveTrack::removeLeg()
{
    if ( selectedLegId != -1 )
    {
        if ( selectedLegId == _activeLeg )
        {
            FTMessageBox::Error( tr("Unable to delete"),
                                tr("Unable to delete the active leg") );
        }
        else
        {
            if ( FTMessageBox::Yesno( tr("Delete leg"),
                                      tr("Really delete leg?") ) )
            {
                _track->deleteLeg( selectedLegId );
                autosaver.AutosaveDeleteLeg( selectedLegId );
                closeLegEdit();
                populateListLegs();
            }
        }
    }
}

void LiveTrack::confirmLeg()
{
    // Close edit widget first...
    closeLegEdit();

    GPS_leg* myLeg;
    if ( isNewLeg )
    {   // Add new leg and get its ID
        myLeg = new GPS_leg();
        selectedLegId = myLeg->id();
    }
    else
    {   // Get leg from track
        myLeg = _track->legMod( selectedLegId );
    }
    if ( myLeg != NULL )
    {
        // Save color&title
        myLeg->setTitle( legnameEdit->text() );
        myLeg->setColor( tmpLegColor );
        // Update leg to track
        _track->legUpdated( myLeg );
        autosaver.AutosaveLeg( myLeg );

        if ( selectedLegId != _activeLeg )
            if ( activelegButton->isChecked() || (_activeLeg == -1) )
            {
                _activeLeg = selectedLegId;
                autosaver.AutosaveActiveLeg( selectedLegId );
            }

        updateInfoLabel();
        populateListLegs();
    }
}

void LiveTrack::ignoreLeg()
{
    selectedLegId = -1;
    isNewLeg = false;
    closeLegEdit();
}

void LiveTrack::setColorLeg()
{
    tmpLegColor = FTMessageBox::Color( tr("Leg color"), tr("Select color"), tmpLegColor );
    legcolorButton->setCustomBackground( QBrush( tmpLegColor ) );
}

void LiveTrack::changeActiveLeg()
{
    // Remember, you are not allowed to deactivate a leg... only to axtivate it!
    if ( selectedLegId == _activeLeg )
    {
        FTMessageBox::Error( tr("Set active leg"),
                            tr("You cannot deactivate the active leg!") );
        activelegButton->setChecked(true);
    }
    else if ( activelegButton->isChecked() )
    {
        if ( _trackingActive )
            if ( !FTMessageBox::Yesno( tr("Confirm active leg"),
                                           tr("LiveTrack is active, confirm change of active leg?")) )
            activelegButton->setChecked(false);
    }
}

void LiveTrack::updateInfoLabel()
{
    infoLabel->setText(QString("%1km \\ %2pts").arg(_track->totalLength()/1000).arg(_track->totalPoints()));
}

void LiveTrack::pageChanged()
{
    if ( livetrackTab->currentWidget() == stats )
        stats->setTrack( track() );
}

QLayout* LiveTrack::createHorizontal()
{
    return createVertical();
}

QLayout* LiveTrack::createVertical()
{
    FTVBoxLayout* vgrid;
    FTHBoxLayout* hgrid;

    // Layout main page:
    if ( mainPage->layout() != NULL )
        delete mainPage->layout();
    vgrid = new FTVBoxLayout();
    // title/description
    vgrid->addWidget( titleLabel );
    vgrid->addWidget( titleEdit );
    vgrid->addWidget( descLabel );
    vgrid->addWidget( descEdit );
    // filename
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( filenamesaveButton );
    hgrid->addWidget( filenameloadButton );
    hgrid->addWidget( filenameLabel );
    vgrid->addLayout( hgrid );
    // start and reset
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( startButton, 2 );
    hgrid->addWidget( resetButton );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( infoLabel );
    vgrid->addStretch();
    mainPage->setLayout( vgrid );

    // Layout legs page:
    if ( legsPage->layout() != NULL )
        delete legsPage->layout();
    vgrid = new FTVBoxLayout();
    vgrid->addWidget( newlegButton );
    vgrid->addWidget( legsList );
    vgrid->addWidget( editlegPane );
    legsPage->setLayout( vgrid );
    if ( editlegPane->layout() != NULL )
        delete editlegPane->layout();
    vgrid = new FTVBoxLayout();
    vgrid->addWidget( legnameLabel );
    vgrid->addWidget( legnameEdit );
    vgrid->addWidget( legcolorButton, 2 );
    vgrid->addWidget( activelegButton );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( savelegButton );
    hgrid->addWidget( ignorelegButton );
    hgrid->addWidget( deletelegButton );
    vgrid->addLayout( hgrid );
    vgrid->addStretch();
    editlegPane->setLayout( vgrid );

    // Layout waypoints page:
    if ( waypointsPage->layout() != NULL )
        delete waypointsPage->layout();
    vgrid = new FTVBoxLayout();
    vgrid->addWidget( waypointsList );
    vgrid->addWidget( editwaypointPane );
    waypointsPage->setLayout( vgrid );
    if ( editwaypointPane->layout() != NULL )
        delete editwaypointPane->layout();
    vgrid = new FTVBoxLayout();
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( waypointnameLabel );
    hgrid->addWidget( gotoButton );
    vgrid->addLayout( hgrid );
    vgrid->addWidget( waypointnameEdit );
    vgrid->addWidget( waypointdescLabel );
    vgrid->addWidget( waypointdescEdit );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( waypointcolorButton );
    hgrid->addWidget( waypointlatlonEdit );
    vgrid->addLayout( hgrid );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( waypointeleLabel );
    hgrid->addWidget( waypointeleEdit );
    vgrid->addLayout( hgrid );
    hgrid = new FTHBoxLayout();
    hgrid->addWidget( savewaypointButton );
    hgrid->addWidget( ignorewaypointButton );
    hgrid->addWidget( deletewaypointButton );
    vgrid->addLayout( hgrid );
    vgrid->addStretch();
    editwaypointPane->setLayout( vgrid );

    FTVBoxLayout* grid = new FTVBoxLayout();
    grid->addWidget( livetrackTab );
    return grid;
}
